/*
 * File:   fe_bubble.h
 * Author: boyan
 *
 * Created on December 10, 2007, 5:03 PM
 */

#ifndef _FE_BUBBLE_H
#define	_FE_BUBBLE_H

#include "glodef.h"
#include "grid3d.h"
#include "vecs.h"

/* the extended grid data used by the bubble element */

/* NOTE: we leave the original grid structure untouched with one exception:
 *      we add nodes at the end of the nodes array.  The remaining data, which
 *      is specific to bubble we keep in the extended data structure.
 */
typedef struct
{
    int nodes[5];
    int dofs[15];
} bub_elem_t;

typedef struct
{
    unsigned id; /* identifies bub_extend_t structure */
    int bubNN; /* = grid->NN + grid->NEL */
    bub_elem_t *b_el;
} bub_extend_t;


#ifdef	__cplusplus
extern "C"
{
#endif

    void InitBubble(grid3d_t *grid);
    void DoneBubble(grid3d_t *grid);

    int ndof_bub(const grid3d_t *grid);
    int ndof_bub_vec(const grid3d_t *grid);
    void dof_coords_bub(const grid3d_t *grid, node_t *nodes, int dof, double **coords);
    void dof_coords_bub_vec(const grid3d_t *grid, node_t *nodes, int dof, double **coords);
    unsigned dof_bcond_bub(const grid3d_t *grid, int dof);
    unsigned dof_bcond_bub_vec(const grid3d_t *grid, int dof);
    unsigned dof_bdry_bub(const grid3d_t *grid, int dof);
    unsigned dof_bdry_bub_vec(const grid3d_t *grid, int dof);

    int nodes_bub(const grid3d_t *grid, int el, int **nodes);
    int nodes_bub_vec(const grid3d_t *grid, int el, int **nodes);
    int dofs_bub(const grid3d_t *grid, int el, int **dofs);
    int dofs_bub_vec(const grid3d_t *grid, int el, int **dofs);

    void local_stif_bub(const grid3d_t *grid, const elem_t *T, double ***S);
    void local_stif_bub_vec(const grid3d_t *grid, const elem_t *T, double ***S);
    void local_mass_bub(const grid3d_t *grid, const elem_t *T, double ***M);
    void local_mass_bub_vec(const grid3d_t *grid, const elem_t *T, double ***M);
    void local_bub_grad_bub(const grid3d_t *grid, const elem_t *T, double ***S);
    void local_curl_bub_curl_bub(const grid3d_t *grid, const elem_t *T, double ***R);
    void local_div_bub_div_bub(const grid3d_t *grid, const elem_t *T, double ***R);

    void local_advm_bub(const grid3d_t *grid, const elem_t *T, double **AV, double ***M);
    void local_advm_D_bub(const grid3d_t *grid, const elem_t *T, double **AV, double ***M);
    void local_advm_bub_vec(const grid3d_t *grid, const elem_t *T, double **AV, double ***M);
    void local_advm_D_bub_vec(const grid3d_t *grid, const elem_t *T, double **AV, double ***M);

    void local_adjoint_B_bub_vec(const grid3d_t *grid, const elem_t *T, double **AV, double ***_M);
    void local_adjoint_C_bub_vec(const grid3d_t *grid, const elem_t *T, double **AV, double ***_M);
    void local_adjoint_curl_bub_vec(const grid3d_t *grid, const elem_t *T, double **AV, double ***_M);


    void test_scalar_field_bub(const grid3d_t *grid, double time, field3d *field, scalar A);
    void test_vector_field_bub(const grid3d_t *grid, double time, field3d *field, vector A);

    void test_grad_p1_in_bub(const grid3d_t *grid, const scalar p, vector u);
    void test_grad_bub_in_bub(const grid3d_t *grid, const scalar p, vector u);
    void test_p1_in_div_bub(const grid3d_t *grid, const scalar p, vector g);
    void test_bub_in_grad_p1(const grid3d_t *grid, const vector u, scalar q);
    void test_div_bub_in_p1(const grid3d_t *grid, const vector u, scalar q);

    void test_grad_bub_in_grad_bub_scal(const grid3d_t *grid, scalar p, scalar q);
    void test_grad_bub_in_grad_bub_vec(const grid3d_t *grid, vector u, vector v);
    void test_curl_bub_in_curl_bub_vec(const grid3d_t *grid, vector u, vector v);


    void test_bub_grad_bub_in_grad_p1(const grid3d_t *grid, vector u,
        vector v, scalar q);

    void surf_test_n_cross_curl_bub_in_grad_p1(const grid3d_t *grid,
        vector u, scalar q);
    void surf_test_bub_dot_n_in_p1(const grid3d_t *grid,
        vector u, scalar q);



    void interpolate_scalar_lagr_bub(const grid3d_t *grid, double time, field3d *F, scalar s);
    void interpolate_vector_lagr_bub(const grid3d_t *grid, double time, field3d *F, vector s);

    double norm_vec_diff_l2_bub(const grid3d_t *grid, vector v1,
        const vector v2);
    double norm_vec_diff_h1_bub(const grid3d_t *grid, vector v1,
        const vector v2);
    double norm_scal_diff_l2_bub(const grid3d_t *grid, scalar v1,
        const scalar v2);
    double norm_scal_diff_h1_bub(const grid3d_t *grid, const scalar *v1,
        const scalar v2);


#ifdef	__cplusplus
}
#endif

#endif	/* _FE_BUBBLE_H */

